package com.gzc.just.play.last.war.common.message.handler;

import com.gzc.just.play.last.war.common.battle.BattleManager;
import com.gzc.just.play.last.war.common.service.GameService;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.util.Map;
import java.util.concurrent.CompletableFuture;

/**
 * Battle message handler
 */
@Component
public class BattleHandler implements MessageHandlerInterface {

    private static final Logger log = LoggerFactory.getLogger(BattleHandler.class);

    private final BattleManager battleManager;
    private final GameService gameService;
    private final ObjectMapper objectMapper;
    
    public BattleHandler(BattleManager battleManager, GameService gameService, ObjectMapper objectMapper) {
        this.battleManager = battleManager;
        this.gameService = gameService;
        this.objectMapper = objectMapper;
    }

    @Override
    public void handle(Long playerId, Object messageData) {
        try {
            Map<String, Object> data = objectMapper.convertValue(messageData, Map.class);
            String action = (String) data.get("action");
            
            switch (action) {
                case "quick_match":
                    handleQuickMatch(playerId, data);
                    break;
                case "join_room":
                    handleJoinRoom(playerId, data);
                    break;
                case "leave_room":
                    handleLeaveRoom(playerId);
                    break;
                case "start_battle":
                    handleStartBattle(playerId, data);
                    break;
                case "battle_action":
                    handleBattleAction(playerId, data);
                    break;
                default:
                    log.warn("Unknown battle action: {}", action);
            }
        } catch (Exception e) {
            log.error("Error processing battle message for player: {}", playerId, e);
        }
    }
    
    /**
     * Handle quick match
     */
    private void handleQuickMatch(Long playerId, Map<String, Object> data) {
        String gameMode = (String) data.getOrDefault("gameMode", "standard");
        
        log.debug("Player {} requesting quick match with mode: {}", playerId, gameMode);
        
        // Find match through battle manager
        CompletableFuture<Long> matchFuture = battleManager.findMatch(playerId, gameMode);
        
        matchFuture.thenAccept(matchId -> {
            if (matchId != null) {
                log.debug("Found match {} for player {}", matchId, playerId);
                
                // Notify client
                gameService.notifyPlayer(playerId, Map.of(
                    "type", "match_found",
                    "matchId", matchId,
                    "gameMode", gameMode
                ));
            } else {
                log.debug("No match found for player {}", playerId);
                
                // Notify client
                gameService.notifyPlayer(playerId, Map.of(
                    "type", "match_searching"
                ));
            }
        });
    }
    
    /**
     * Handle join room
     */
    private void handleJoinRoom(Long playerId, Map<String, Object> data) {
        String roomId = (String) data.get("roomId");
        String password = (String) data.getOrDefault("password", "");
        
        log.debug("Player {} trying to join room {} with password: {}", 
                 playerId, roomId, password);
        
        // Join room through battle manager
        battleManager.joinRoom(playerId, roomId, password)
            .thenAccept(success -> {
                if (success) {
                    log.debug("Player {} successfully joined room {}", playerId, roomId);
                    
                    // Notify client
                    gameService.notifyPlayer(playerId, Map.of(
                        "type", "room_joined",
                        "roomId", roomId
                    ));
                } else {
                    log.debug("Player {} failed to join room {}", playerId, roomId);
                    
                    // Notify client
                    gameService.notifyPlayer(playerId, Map.of(
                        "type", "room_join_failed",
                        "reason", "invalid_password"
                    ));
                }
            })
            .exceptionally(throwable -> {
                log.error("Error joining room {} for player {}", roomId, playerId, throwable);
                
                // Notify client
                gameService.notifyPlayer(playerId, Map.of(
                    "type", "room_join_failed",
                    "reason", "server_error"
                ));
                
                return null;
            });
    }
    
    /**
     * Handle leave room
     */
    private void handleLeaveRoom(Long playerId) {
        log.debug("Player {} leaving current room", playerId);
        
        // Leave room through battle manager
        battleManager.leaveRoom(playerId)
            .thenAccept(success -> {
                if (success) {
                    log.debug("Player {} successfully left room", playerId);
                    
                    // Notify client
                    gameService.notifyPlayer(playerId, Map.of(
                        "type", "room_left"
                    ));
                } else {
                    log.debug("Player {} was not in a room", playerId);
                }
            })
            .exceptionally(throwable -> {
                log.error("Error leaving room for player {}", playerId, throwable);
                
                // Notify client
                gameService.notifyPlayer(playerId, Map.of(
                    "type", "room_leave_failed",
                    "reason", "server_error"
                ));
                
                return null;
            });
    }
    
    /**
     * Handle start battle
     */
    private void handleStartBattle(Long playerId, Map<String, Object> data) {
        String roomId = (String) data.get("roomId");
        
        log.debug("Player {} requesting to start battle in room {}", playerId, roomId);
        
        // Start battle through battle manager
        battleManager.startBattle(roomId, playerId)
            .thenAccept(success -> {
                if (success) {
                    log.debug("Battle started in room {} by player {}", roomId, playerId);
                    
                    // Notify client
                    gameService.notifyPlayer(playerId, Map.of(
                        "type", "battle_started",
                        "roomId", roomId
                    ));
                } else {
                    log.debug("Failed to start battle in room {} by player {}", roomId, playerId);
                    
                    // Notify client
                    gameService.notifyPlayer(playerId, Map.of(
                        "type", "battle_start_failed",
                        "reason", "not_ready"
                    ));
                }
            })
            .exceptionally(throwable -> {
                log.error("Error starting battle in room {} for player {}", roomId, playerId, throwable);
                
                // Notify client
                gameService.notifyPlayer(playerId, Map.of(
                    "type", "battle_start_failed",
                    "reason", "server_error"
                ));
                
                return null;
            });
    }
    
    /**
     * Handle battle action
     */
    private void handleBattleAction(Long playerId, Map<String, Object> data) {
        String action = (String) data.get("action");
        Map<String, Object> actionData = (Map<String, Object>) data.getOrDefault("data", Map.of());
        
        log.debug("Player {} performing battle action: {}", playerId, action);
        
        // Process action through battle manager
        battleManager.processBattleAction(playerId, action, actionData)
            .thenAccept(result -> {
                if (result != null) {
                    log.debug("Battle action {} processed for player {}", action, playerId);
                    
                    // Notify client
                    gameService.notifyPlayer(playerId, Map.of(
                        "type", "battle_action_result",
                        "action", action,
                        "result", result
                    ));
                } else {
                    log.debug("Invalid battle action {} for player {}", action, playerId);
                    
                    // Notify client
                    gameService.notifyPlayer(playerId, Map.of(
                        "type", "battle_action_failed",
                        "action", action,
                        "reason", "invalid_action"
                    ));
                }
            })
            .exceptionally(throwable -> {
                log.error("Error processing battle action {} for player {}", action, playerId, throwable);
                
                // Notify client
                gameService.notifyPlayer(playerId, Map.of(
                    "type", "battle_action_failed",
                    "action", action,
                    "reason", "server_error"
                ));
                
                return null;
            });
    }
}